﻿using System;
using System.Collections;
using System.IO;
using System.Net;
using System.Text;
using System.Threading;
using Alserve.Ffl.Data;
using HtmlAgilityPack;

namespace Alserve.Ffl
{

    public class EspnImport
    {
        public EspnImport()
        {
        }

        private HtmlAgilityPack.HtmlDocument ReadHtmlDocument(string url)
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            
            request.AllowAutoRedirect = false;
            request.Proxy = null;
            request.UseDefaultCredentials = true;

            CookieContainer cc = new CookieContainer();
            request.CookieContainer = cc;

            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.Default);

            HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
            doc.Load(sr);

            return doc;
        }

        public void ImportTransfers()
        {
            Club thisClub = new Club();
            thisClub.LoadAll();

            do
            {
                ImportTransfers(thisClub.Id);
                Thread.Sleep(300);
            }
            while (thisClub.MoveNext());

        }

        public void ImportTransfers(Int32 clubId)
        {
            //Get ESPN ClubId
            EspnClub thisEspnClub = new EspnClub();
            thisEspnClub.Where.ClubId.Value = clubId;

            if (thisEspnClub.Query.Load())
            {
                Int32 espnClubId = thisEspnClub.EspnClubId;
                

                for (int positionCount = 1; positionCount <= 4; positionCount++)
                {
                    String espnPositionNumber = "";
                    Position thisPosition = new Position();

                    switch (positionCount)
                    {
                        case 1:
                            espnPositionNumber = "1";
                            thisPosition.Where.PositionShort.Value = "G";
                            break;
                        case 2:
                            espnPositionNumber = "2";
                            thisPosition.Where.PositionShort.Value = "D";
                            break;
                        case 3:
                            espnPositionNumber = "10";
                            thisPosition.Where.PositionShort.Value = "M";
                            break;
                        case 4:
                            espnPositionNumber = "18";
                            thisPosition.Where.PositionShort.Value = "F";
                            break;
                    }

                    thisPosition.Query.Load();
                    Int32 positionId = thisPosition.Id;

                    String url = "http://soccernet.espn.go.com/format/design09/clubhouse/getRosterPlayersTable?teamId=" + espnClubId.ToString() + "&positionId=" + espnPositionNumber + "&leagueId=23&season=" + DateTime.Today.Year.ToString() + "&lang=EN&cc=5739";

                    foreach (HtmlNode table in this.ReadHtmlDocument(url).DocumentNode.SelectNodes("//table[@class=\"tablehead\"][@border=0]"))
                    {
                        foreach (HtmlNode row in table.SelectNodes("tbody/tr[@class=\"oddrow\" or @class=\"evenrow\"]"))
                        {
                            foreach (HtmlNode cell in row.SelectNodes("td"))
                            {
                                if (cell.SelectNodes("a") != null)
                                {

                                    //<td align="left"><a href="http://soccernet.espn.go.com/player/_/id/14582/manuel-almunia" >Manuel Almunia</a></td>
                                    String playerName = cell.SelectSingleNode("a").InnerText.Trim();
                                    playerName = playerName.Replace("&#", "[amp;hash;]");
                                    String espnRef = cell.SelectSingleNode("a").Attributes["href"].Value;
                                    espnRef = espnRef.Substring(espnRef.IndexOf("/id/") + 4);
                                    Int32 espnId = Convert.ToInt32(espnRef.Substring(0, espnRef.IndexOf("/")));

                                    //Does this player have an ESPN ref
                                    _PlayerView thisPlayerView = new _PlayerView();
                                    thisPlayerView.Where.EspnPlayerId.Value = espnId;

                                    Transfer thisTransfer = new Transfer();

                                    if (thisPlayerView.Query.Load())
                                    {
                                        //This is an existing player
                                        //Does player still play for the same club
                                        if (thisPlayerView.ClubId != clubId)
                                        {
                                            thisTransfer.AddNew();
                                            thisTransfer.NewPlayer = false;
                                            thisTransfer.PlayerId = thisPlayerView.PlayerId;
                                            thisTransfer.ClubId = clubId;
                                            thisTransfer.EspnRef = espnId;
                                            thisTransfer.PositionId = positionId;
                                            thisTransfer.Save();
                                        }
                                    }
                                    else
                                    {
                                        //This is a new player
                                        thisTransfer.AddNew();
                                        thisTransfer.NewPlayer = true;
                                        thisTransfer.ClubId = clubId;
                                        thisTransfer.EspnRef = espnId;
                                        thisTransfer.PlayerName = playerName;
                                        thisTransfer.PositionId = positionId;
                                        thisTransfer.Save();
                                    }
                                }
                            }
                        }
                    }



                }

                
                
            }
        }

        public void ImportNewsFeed()
        {
            NewsFeed thisNewsFeed = new NewsFeed();
            thisNewsFeed.LoadAll();
            thisNewsFeed.DeleteAll();
            thisNewsFeed.Save();

            HtmlNode divNode = ReadHtmlDocument("http://www.footballnewsfeeds.com/").DocumentNode.SelectSingleNode("/html/body//div[@id=\"content\"]");

            Int32 feedCount = divNode.SelectNodes("h2").Count;

            for (Int32 divCount = 0; divCount < feedCount; divCount++)
            {
                //65533 = the question mark character
                String linkURL = divNode.SelectNodes("h2/a")[divCount].Attributes["href"].Value.Trim();
                String linkText = divNode.SelectNodes("h2/a")[divCount].InnerText.Trim();
                String imageURL = string.Empty;
                try
                {
                    imageURL = divNode.SelectNodes("p/img")[divCount].Attributes["src"].Value.Trim();
                }
                catch { }
                
                String contentText = divNode.SelectNodes("p")[divCount].InnerText.Trim();

                if (linkText.Length > 255)
                    linkText = linkText.Substring(0, 255);

                if (contentText.Length > 255)
                    contentText = contentText.Substring(0, 255);

                //<em>Football | Mail Online 24 Jun 02:29</em>
                String emText = divNode.SelectNodes("em")[divCount].InnerText.Trim();
                emText = emText.Substring(emText.Length - 12, 12);

                Int32 feedDay = Convert.ToInt32(emText.Substring(0, 2).Trim());
                Int32 feedMonth = Convert.ToDateTime(emText.Substring(3, 3).Trim() + " 01,1900").Month;
                Int32 feedHour = Convert.ToInt32(emText.Substring(7, 2).Trim());
                Int32 feedMinute = Convert.ToInt32(emText.Substring(10, 2).Trim());
                DateTime feedDate = new DateTime(DateTime.Now.Year, feedMonth, feedDay, feedHour, feedMinute, 0);
                if (feedDate >= DateTime.Now)
                    feedDate.AddYears(-1);

                thisNewsFeed.AddNew();
                thisNewsFeed.NewsDate = feedDate;
                thisNewsFeed.Headline = linkText;
                thisNewsFeed.Details = contentText;
                thisNewsFeed.Url = linkURL;
                thisNewsFeed.ImageURL = imageURL;
                thisNewsFeed.Save();
            }
        }


        public ArrayList GetNewMatchesByCompetitionAndDate(Int32 competitionId, DateTime viewDate)
        {
            ArrayList returnValue = new ArrayList();

            String espnCompetitionId = String.Empty;
            switch (competitionId)
            {
                case 1:
                    espnCompetitionId = "eng.1/barclays-premier-league";
                    break;
                case 2:
                    espnCompetitionId = "eng.fa/english-fa-cup";
                    break;
                case 3:
                    espnCompetitionId = "uefa.champions/uefa-champions-league";
                    break;
                case 4:
                    espnCompetitionId = "uefa.europa/uefa-europa-league";
                    break;
            }

            //String todayDate = viewDate.ToString("yyyyMMdd");
            HtmlWeb web = new HtmlWeb();
            web.UsingCache = false;
            //HtmlDocument document = web.Load("http://soccernet.espn.go.com/fixtures?league=" + espnCompetitionId + "&date=" + firstOfMonthDate + "&type=month&cc=5739");
            //http://soccernet.espn.go.com/results/_/date/20101128/league/eng.1/barclays-premier-league?cc=5739
            //http://soccernet.espn.go.com/results/_/league/eng.1/english-premier-league?cc=5739
            HtmlDocument document = web.Load("http://soccernet.espn.go.com/results/_/league/" + espnCompetitionId + "?cc=5739");
           

            foreach (HtmlNode table in document.DocumentNode.SelectNodes("//table[@class=\"tablehead\"][tr/td[@colspan=\"7\" or @colspan=\"6\"]]"))
            {
                String matchDateString = competitionId == 1 || competitionId == 2 ? table.SelectSingleNode("tr/td[@colspan=\"7\"]").InnerText : table.SelectSingleNode("tr/td[@colspan=\"6\"]").InnerText;
                DateTime matchDate = Convert.ToDateTime(matchDateString);

                foreach (HtmlNode row in table.SelectNodes("tr[@class!=\"stathead\"][@class!=\"colhead\"]"))
                {
                    Boolean fullTime = false;
                    Int32 homeClubEspnId = -1;
                    Int32 awayClubEspnId = -1;
                    Int32 espnMatchId = -1;
                    String matchURL = String.Empty;
                    ImportedMatch matchItem = new ImportedMatch();

                    for (Int32 cellCount = 0; cellCount <= row.SelectNodes("td").Count - 1; cellCount++)
                    {
                        HtmlNode cell = row.SelectNodes("td")[cellCount];
                        switch (cellCount)
                        {
                            case 0:
                                fullTime = (cell.InnerText == "FT" || cell.InnerText == "FT-Pens" || cell.InnerText == "AET");
                                break;
                            case 1:
                                if (cell.SelectSingleNode("a") != null)
                                {
                                    HtmlAttribute clubURL = cell.SelectSingleNode("a").Attributes["href"];
                                    homeClubEspnId = Convert.ToInt32(FflCommon.GetTextBetween(clubURL.Value, "espnfc.com/team/_/id/", "/"));
                                }
                                break;
                            case 2:
                                if (fullTime)
                                {
                                    matchURL = cell.SelectSingleNode("a").Attributes["href"].Value;
                                    if(matchURL.IndexOf("/uk/en/report/") > -1)
                                        espnMatchId = Convert.ToInt32(FflCommon.GetTextBetween(matchURL, "/uk/en/report/", "/report.html"));
                                    else if (matchURL.IndexOf("/uk/en/gamecast/") > -1)
                                        espnMatchId = Convert.ToInt32(FflCommon.GetTextBetween(matchURL, "/uk/en/gamecast/", "/gamecast.html"));
                                }
                                break;
                            case 3:

                                if (cell.SelectSingleNode("a") != null)
                                {
                                    HtmlAttribute clubURL = cell.SelectSingleNode("a").Attributes["href"];
                                    awayClubEspnId = Convert.ToInt32(FflCommon.GetTextBetween(clubURL.Value, "espnfc.com/team/_/id/", "/"));
                                }
                                break;
                        }
                    }

                    //Does either club exist
                    EspnClub thisEspnClub = new EspnClub();
                    thisEspnClub.Where.EspnClubId.Value = homeClubEspnId;
                    Boolean homeClubExists = thisEspnClub.Query.Load();
                    
                    thisEspnClub = new EspnClub();
                    thisEspnClub.Where.EspnClubId.Value = awayClubEspnId;
                    Boolean awayClubExists = thisEspnClub.Query.Load();
                
                    if (fullTime && (homeClubExists || awayClubExists))
                    {
                        matchItem.EspnMatchId = espnMatchId;
                        matchItem.MatchDate = matchDate;
                        if (homeClubExists)
                            matchItem.HomeClubEspnId = homeClubEspnId;
                        if(awayClubExists)
                            matchItem.AwayClubEspnId = awayClubEspnId;
                        matchItem.CompetitionId = competitionId;
                        returnValue.Add(matchItem);
                    }
                }
            }
            returnValue.Sort();
            return returnValue;
        }


        public ImportedMatch GetMatchByEspnMatchId(Int32 espnMatchId, Int32 competitionId, DateTime matchDate)
        {
            ImportedMatch returnValue = new ImportedMatch();
            returnValue.MatchId = espnMatchId;
            returnValue.MatchDate = matchDate;

            String espnCompetitionId = String.Empty;
            switch (competitionId)
            {
                case 1:
                    espnCompetitionId = "eng.1";
                    break;
                case 2:
                    espnCompetitionId = "eng.fa";
                    break;
                case 3:
                    espnCompetitionId = "uefa.champions";
                    break;
                case 4:
                    espnCompetitionId = "uefa.europa";
                    break;
            }
            
            HtmlWeb web = new HtmlWeb();
            web.UsingCache = false;
            
            string url = "http://espnfc.com/uk/en/gamecast/statistics/id/" + espnMatchId.ToString() + "/statistics.html?soccernet=true&cc=5739";
            //Get match details
            HtmlDocument document = ReadHtmlDocument(url);

            foreach (HtmlNode header in document.DocumentNode.SelectNodes("//div[@class=\"matchup\"]"))
            {
                returnValue.HomeClubEspnId = Convert.ToInt32(Alserve.Ffl.FflCommon.GetTextBetween(header.SelectNodes("div/a")[0].Attributes["href"].Value, "team/_/id/","/"));
                EspnClub thisEspnClub = new EspnClub();
                thisEspnClub.Where.EspnClubId.Value = returnValue.HomeClubEspnId;
                if (thisEspnClub.Query.Load())
                    returnValue.HomeClubId = thisEspnClub.Id;

                returnValue.AwayClubEspnId = Convert.ToInt32(Alserve.Ffl.FflCommon.GetTextBetween(header.SelectNodes("div/a")[1].Attributes["href"].Value, "team/_/id/","/"));
                thisEspnClub = new EspnClub();
                thisEspnClub.Where.EspnClubId.Value = returnValue.AwayClubEspnId;
                if (thisEspnClub.Query.Load())
                    returnValue.AwayClubId = thisEspnClub.Id;

                string working = header.SelectSingleNode("div[@class=\"score-time\"]/div/p[@class=\"score\"]").InnerText;
                working = working.Replace("/r", "");
                working = working.Replace("/n", "");
                working = working.Replace("/t", "").Trim();
                
                //Fix for games decided by penalties - e.g. (3)1 - 1(4)
                if (working.IndexOf(")") > -1)
                {
                    working = Alserve.Ffl.FflCommon.GetTextAfter(working, ")");
                    working = Alserve.Ffl.FflCommon.GetTextBefore(working, "(");
                }

                returnValue.HomeGoals = Convert.ToInt32(Alserve.Ffl.FflCommon.GetTextBefore(working, "-").Trim());
                returnValue.AwayGoals = Convert.ToInt32(Alserve.Ffl.FflCommon.GetTextAfter(working, "-").Trim());
            }

            ArrayList playerList = new ArrayList();
            bool homeFlag = true;

            foreach (HtmlNode table in document.DocumentNode.SelectNodes("//table[@class=\"stat-table\"]"))
            {
                bool hasCleanSheet = homeFlag ? returnValue.AwayGoals == 0 : returnValue.HomeGoals == 0;
                bool hasConcededOne = homeFlag ? returnValue.AwayGoals == 1 : returnValue.HomeGoals == 1;
                bool hasTeamScoredThreePlus = homeFlag ? returnValue.HomeGoals >= 3 : returnValue.AwayGoals >= 3;

                bool isSubstitute = false;

                foreach (HtmlNode row in table.SelectNodes("tbody/tr"))
                {
                    if (row.SelectSingleNode("th") != null)
                    {
                        if (row.SelectSingleNode("th").Attributes["class"] != null)
                            if (row.SelectSingleNode("th").Attributes["class"].Value == "tb-substitutes home-team" || row.SelectSingleNode("th").Attributes["class"].Value == "tb-substitutes away-team")
                                isSubstitute = true;
                    }

                    if (row.SelectSingleNode("td") == null || row.SelectNodes("td").Count < 3)
                        continue;

                    string working = row.SelectNodes("td")[2].SelectSingleNode("a").Attributes["href"].Value;

                    int espnPlayerId = Convert.ToInt32(Alserve.Ffl.FflCommon.GetTextBetween(working, "player/_/id/", "/"));

                    bool hasPlayedAsSub = false;
                    int playerGoals = 0;

                    if (row.SelectNodes("td")[2].SelectSingleNode("div") != null)
                    {
                        foreach (HtmlNode div in row.SelectNodes("td")[2].SelectNodes("div"))
                        {
                            if (div.Attributes["class"].Value == "soccer-icons soccer-icons-subinout")
                                hasPlayedAsSub = true;

                            if (div.Attributes["class"].Value == "soccer-icons soccer-icons-goal")
                                playerGoals++;
                        }
                    }

                    if (isSubstitute && !hasPlayedAsSub)
                        continue;
                    
                    if (DoesPlayerExist(espnPlayerId))
                    {
                        ImportedMatchPlayer thisPlayer = null;
                        bool newPlayer = !HasPlayerAlreadyBeenAddedToMatch(playerList, espnPlayerId, ref thisPlayer);

                        thisPlayer.Started = !isSubstitute;
                        thisPlayer.PlayedAsSub = hasPlayedAsSub;
                        thisPlayer.CleanSheet = hasCleanSheet;
                        thisPlayer.ConcededOne = hasConcededOne;
                        thisPlayer.TeamScoredThreePlus = hasTeamScoredThreePlus;
                        thisPlayer.Goals = playerGoals;

                        if (newPlayer)
                        {
                            thisPlayer.EspnPlayerId = espnPlayerId;
                            playerList.Add(thisPlayer);
                        }
                    }
                }

                homeFlag = false;
            }

            playerList.Sort();
            returnValue.PlayerList = playerList;
            return returnValue;
        }

        private Boolean HasPlayerAlreadyBeenAddedToMatch(ArrayList playerList, Int32 espnPlayerId, ref ImportedMatchPlayer returnMatchPlayer)
        {
            Boolean returnValue = false;
           
            if (playerList != null)
            {
                foreach (ImportedMatchPlayer thisMatchPlayer in playerList)
                {
                    if (thisMatchPlayer.EspnPlayerId == espnPlayerId)
                    {
                        returnMatchPlayer = thisMatchPlayer;
                        returnValue = true;
                        break;
                    }
                }
            }
        
            if (!returnValue)
                returnMatchPlayer = new ImportedMatchPlayer();

            return returnValue;
        }

        private Boolean DoesPlayerExist(Int32 espnPlayerId)
        {
            EspnPlayer thisEspnPlayer = new EspnPlayer();
            thisEspnPlayer.Where.EspnPlayerId.Value = espnPlayerId;
            Boolean returnValue = thisEspnPlayer.Query.Load();
            return returnValue;
        }
    }
}